/*
 * Wazuh Vulnerability scanner
 * Copyright (C) 2015, Wazuh Inc.
 * Nov 1, 2023.
 *
 * This program is free software; you can redistribute it
 * and/or modify it under the terms of the GNU General Public
 * License (version 2) as published by the FSF - Free Software
 * Foundation.
 */

#include "argsParser.hpp"
#include "json.hpp"
#include "socketDBWrapper.hpp"
#include "wazuhDBQueryBuilder.hpp"
#include <iostream>
#include <unordered_map>

auto constexpr WAZUH_DB_SOCK {"/var/ossec/queue/db/wdb"};

const std::unordered_map<std::string, WazuhDBQueryBuilder& (WazuhDBQueryBuilder::*)()> FUNC_MAP {
    {"global", &WazuhDBQueryBuilder::global}, {"selectAll", &WazuhDBQueryBuilder::selectAll}};

const std::unordered_map<std::string, WazuhDBQueryBuilder& (WazuhDBQueryBuilder::*)(const std::string&)> FUNC_ARG_MAP {
    {"agent", &WazuhDBQueryBuilder::agent},
    {"fromTable", &WazuhDBQueryBuilder::fromTable},
    {"equalsTo", &WazuhDBQueryBuilder::equalsTo},
    {"whereColumn", &WazuhDBQueryBuilder::whereColumn},
    {"andColumn", &WazuhDBQueryBuilder::andColumn},
    {"orColumn", &WazuhDBQueryBuilder::orColumn},
    {"globalGetCommand", &WazuhDBQueryBuilder::globalGetCommand},
    {"globalFindCommand", &WazuhDBQueryBuilder::globalFindCommand},
    {"globalSelectCommand", &WazuhDBQueryBuilder::globalSelectCommand},
    {"agentGetOsInfoCommand", &WazuhDBQueryBuilder::agentGetOsInfoCommand},
    {"agentGetHotfixesCommand", &WazuhDBQueryBuilder::agentGetHotfixesCommand},
    {"agentGetPackagesCommand", &WazuhDBQueryBuilder::agentGetPackagesCommand}};

int main(const int argc, const char* argv[])
{
    try
    {
        CmdLineArgs cmdLineArgs(argc, argv);

        // Read json configuration file
        auto configuration = nlohmann::json::parse(std::ifstream(cmdLineArgs.getConfigurationFilePath()));

        SocketDBWrapper socketDBWrapper(WAZUH_DB_SOCK);
        nlohmann::json response;

        for (const auto& query : configuration.at("queries"))
        {
            auto wazuhDBQueryBuilder = WazuhDBQueryBuilder::builder();

            for (const auto& element : query)
            {
                if (!element.contains("arg"))
                {
                    (wazuhDBQueryBuilder.*(FUNC_MAP.at(element.at("method"))))();
                }
                else
                {
                    (wazuhDBQueryBuilder.*(FUNC_ARG_MAP.at(element.at("method"))))(element.at("arg"));
                }
            }

            auto queryStr = wazuhDBQueryBuilder.build();
            socketDBWrapper.query(queryStr, response);

            std::cout << "Response to \"" << queryStr << "\":\n" << response.dump(4) << std::endl;
        }
    }
    catch (const std::exception& e)
    {
        std::cerr << e.what() << std::endl;
        CmdLineArgs::showHelp();
        return 1;
    }
    return 0;
}
